package com.stylefeng.guns.modular.product.warpper;

import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
import com.stylefeng.guns.core.util.DateUtil;
import com.stylefeng.guns.core.util.FmtMicrometer;
import org.apache.commons.collections.map.HashedMap;

import java.util.*;

public class OptionReportWarpper extends BaseControllerWarpper {

    public OptionReportWarpper(List<Map<String, Object>> list){
        super(list);
    }

    @Override
    protected void warpTheMap(Map<String, Object> map) {
        Double notional = (Double) map.get("notional");
        Double counterValue = (Double) map.get("counterValue");
        Double strike = (Double) map.get("strike");
        String deltaStr = (String) map.get("delta");
        String gammaStr = (String) map.get("gamma");
        Double.parseDouble(deltaStr);

        map.put("expiryDate",DateUtil.getDay((Date) map.get("expiryDate")));
        map.put("deliveryDate",DateUtil.getDay((Date) map.get("deliveryDate")));
        map.put("tradeDate",DateUtil.getDay((Date) map.get("tradeDate")));

        if( notional != null)
            map.put("notional",FmtMicrometer.fmtMicrometer(notional, 0, false));

        if( counterValue != null)
            map.put("counterValue",FmtMicrometer.fmtMicrometer(counterValue, 0, false));

        if( strike != null)
            map.put("strike",FmtMicrometer.fmtMicrometer(strike, 4, false));

        Double premiumAmount = (Double) map.get("premiumAmount");
        if( premiumAmount != null)
            map.put("premiumAmount",FmtMicrometer.fmtMicrometer(premiumAmount, 0, false));

        String midPrice = (String) map.get("midPrice");
        if( midPrice != null)
            map.put("midPrice",FmtMicrometer.fmtMicrometer(Double.parseDouble(midPrice), 0, false));

        map.put("delta",FmtMicrometer.fmtMicrometer(Math.abs(Double.parseDouble(deltaStr))/100*notional, 0, false));

        String vega = (String) map.get("vega");
        if( vega != null)
            map.put("vega",FmtMicrometer.fmtMicrometer(Double.parseDouble(vega), 0, false));

        map.put("gamma",FmtMicrometer.fmtMicrometer(Math.abs(Double.parseDouble(gammaStr))/100*notional, 0, false));

        String theta = (String) map.get("theta");
        if( vega != null)
            map.put("theta",FmtMicrometer.fmtMicrometer(Double.parseDouble(theta), 0, false));

    }

    public Object warpTheList(){
        List<Map<String, Object>> list = (List<Map<String, Object>>) this.obj;
        List<Map<String, Object>> newList = new ArrayList<>();
        String expiryDate = null;
        String productLevel3 = null;
        double premiumAmountSum = 0;
        double midPriceSum = 0;
        double deltaSum = 0;
        double vegaSum = 0;
        double gammaSum = 0;
        double thetaSum = 0;
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = list.get(i);
            String expiryDateStr = DateUtil.getDay((Date) map.get("expiryDate"));
            String productLevel3Str = (String) map.get("productLevel3");
            double premiumAmount = (Double)map.get("premiumAmount");
            double delta = Double.parseDouble((String)map.get("delta"));
            double gamma = Double.parseDouble((String)map.get("gamma"));
            double midPrice = Double.parseDouble((String)map.get("midPrice"));
            double vega = Double.parseDouble((String)map.get("vega"));
            double theta = Double.parseDouble((String)map.get("theta"));

            if(i == 0) {
                expiryDate = expiryDateStr;
                productLevel3 = productLevel3Str;
            }

            if( !(expiryDate.equals(expiryDateStr) && productLevel3.equals(productLevel3Str)) ){
                expiryDate = expiryDateStr;
                productLevel3 = productLevel3Str;

                newList.add(this.createMap(premiumAmountSum,midPriceSum,deltaSum,vegaSum,gammaSum,thetaSum,expiryDateStr+" Total"));

                newList.add(this.updateMap(map));

                premiumAmountSum = premiumAmount;
                midPriceSum = midPrice;
                deltaSum = delta;
                vegaSum = vega;
                gammaSum = gamma;
                thetaSum = theta;

            }else{
                newList.add(this.updateMap(map));
                premiumAmountSum += premiumAmount;
                midPriceSum += midPrice;
                deltaSum += delta;
                vegaSum += vega;
                gammaSum += gamma;
                thetaSum += theta;
            }

            if(i == list.size() -1){
                newList.add(this.createMap(premiumAmountSum,midPriceSum,deltaSum,vegaSum,gammaSum,thetaSum,expiryDateStr+" Total"));
            }

        }
        this.obj = newList;
        return newList;
    }


    private Map<String, Object> createMap(Object premiumAmountSum,Object midPriceSum,Object deltaSum,
                                          Object vegaSum,Object gammaSum,Object thetaSum,Object expiryDate){
        Map<String, Object> newMap = new HashMap<>();
        newMap.put("expiryDate",expiryDate);
        newMap.put("deliveryDate",null);
        newMap.put("tradeDate",null);
        newMap.put("buySell",null);
        newMap.put("productLevel3",null);
        newMap.put("currency1",null);
        newMap.put("notional",null);
        newMap.put("currency2",null);
        newMap.put("counterValue",null);
        newMap.put("strike",null);
        newMap.put("premiumAmount", FmtMicrometer.fmtMicrometer((Double)premiumAmountSum, 0, true));
        newMap.put("midPrice", FmtMicrometer.fmtMicrometer((Double)midPriceSum, 0, true));
        newMap.put("delta", FmtMicrometer.fmtMicrometer((Double)deltaSum, 0, true));
        newMap.put("vega", FmtMicrometer.fmtMicrometer((Double)vegaSum, 0, true));
        newMap.put("gamma", FmtMicrometer.fmtMicrometer((Double)gammaSum, 0, true));
        newMap.put("theta", FmtMicrometer.fmtMicrometer((Double)thetaSum, 0, true));
        newMap.put("strategyCode",null);
        newMap.put("gammaVega",null);
        return newMap;
    }


    private Map<String, Object> updateMap(Map<String, Object> map){

        Double notional = (Double) map.get("notional");
        Double counterValue = (Double) map.get("counterValue");
        Double strike = (Double) map.get("strike");
        String deltaStr = (String) map.get("delta");
        String gammaStr = (String) map.get("gamma");
        Double.parseDouble(deltaStr);

        map.put("expiryDate",DateUtil.getDay((Date) map.get("expiryDate")));
        map.put("deliveryDate",DateUtil.getDay((Date) map.get("deliveryDate")));
        map.put("tradeDate",DateUtil.getDay((Date) map.get("tradeDate")));

        if( notional != null)
            map.put("notional",FmtMicrometer.fmtMicrometer(notional, 0, true));

        if( counterValue != null)
            map.put("counterValue",FmtMicrometer.fmtMicrometer(counterValue, 0, true));

        if( strike != null)
            map.put("strike",FmtMicrometer.fmtMicrometer(strike, 4, true));

        Double premiumAmount = (Double) map.get("premiumAmount");
        if( premiumAmount != null)
            map.put("premiumAmount",FmtMicrometer.fmtMicrometer(premiumAmount, 0, true));

        String midPrice = (String) map.get("midPrice");
        if( midPrice != null)
            map.put("midPrice",FmtMicrometer.fmtMicrometer(Double.parseDouble(midPrice), 0, true));

        map.put("delta",FmtMicrometer.fmtMicrometer(Math.abs(Double.parseDouble(deltaStr))/100*notional, 0, true));

        String vega = (String) map.get("vega");
        if( vega != null)
            map.put("vega",FmtMicrometer.fmtMicrometer(Double.parseDouble(vega), 0, true));

        map.put("gamma",FmtMicrometer.fmtMicrometer(Math.abs(Double.parseDouble(gammaStr))/100*notional, 0, true));

        String theta = (String) map.get("theta");
        if( vega != null)
            map.put("theta",FmtMicrometer.fmtMicrometer(Double.parseDouble(theta), 0, true));

        return map;
    }
}
